package com.partsoft.spring.zks;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.HtmlMacroComponent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.ext.AfterCompose;

/**
 * 公用的数据组件基础类<br/>
 * 用于定义非include等于false的宏组件
 * @author neeker
 */
@SuppressWarnings({"serial"})
public abstract class ExtHtmlMacroComponent extends HtmlMacroComponent {
	
	/**
	 * 数据组件组合后克隆名称前缀
	 */
	public static final String DATA_COMPOSER_CLONE = "DATA_COMPOSER_CLONE";
	
	/**
	 * 克隆组合后事件名称
	 */
	public static final String ON_AFTER_CLONE = "onCLONE_DO_AFTER_COMPOSE";
	
	
	/**
	 * 数据模型参数名
	 */
	public static final String ARG_DATAMODEL = "dataModel";
	
	/**
	 * 数据已经装载事件
	 */
	public static final String ON_DATALOAD = "onDataLoad";
	
	private boolean alreadyCompose;
	
	public ExtHtmlMacroComponent() {
		super();
		//TODO 把宏组件的span标签设置为block，否则。。居然不显示。。为啥？？？
		this.setStyle("display: block");
	}
	
	/**
	 * 始终设置inline等于false
	 */
	@Override
	final public boolean isInline() {
		return false;
	}
	
	/**
	 * 编程创建数据宏组件构造函数
	 * @param macroURI
	 */
	public ExtHtmlMacroComponent(String macroURI) {
		this.setMacroURI(macroURI);
	}
	
	/**
	 * 编程创建数据宏组件构造函数
	 * @param parent 指定父组件
	 * @param macroURI
	 */
	public ExtHtmlMacroComponent(Component parent, String macroURI) {
		this.setMacroURI(macroURI);
	}
	
	/**
	 * 下属子组件组合后被调用
	 */
	@Override
	public void afterCompose() {
		if (isAlreadyCompose()) return;
		beforeCreateMacroChildren();
		super.afterCompose();
		afterCreateMacroChildren();
		this.alreadyCompose = true;
	}
	
	/**
	 * 在创建宏组件之前被调用方法
	 */
	protected void beforeCreateMacroChildren() {}
	
	/**
	 * 在创建宏组件之后被调用的方法
	 */
	protected void afterCreateMacroChildren() {}
	
	/**
	 * 重新创建方法
	 */
	@Override
	public void recreate() {
		alreadyCompose = false;
		super.recreate();
	}
	
	/**
	 * 由于Macro实现了{@link AfterCompose}接口，因此创建之后会重入{@link #afterCompose()}
	 * @return 返回true表示已经调用了组合方法
	 */
	final public boolean isAlreadyCompose() {
		return alreadyCompose;
	}
	
	@Override
	public Object clone() {
		ExtHtmlMacroComponent clone = (ExtHtmlMacroComponent) super.clone();
		clone.addEventListener(ON_AFTER_CLONE, new DataComponentAfterCloneEventListener());
		Events.postEvent(new Event(ON_AFTER_CLONE, clone));
		return clone;
	}
	
	/**
	 * 克隆后调用方法(在组合实现之后被调用)
	 */
	protected void doAfterClone() {
		
	}
	
	/**
	 * 数据组件克隆后事件, 仅执行一次
	 * @author neeker
	 */
	private static class DataComponentAfterCloneEventListener implements EventListener<Event> {
		public void onEvent(Event event) throws Exception {
			final ExtHtmlMacroComponent clone = (ExtHtmlMacroComponent) event.getTarget();
			clone.doAfterClone();
			clone.removeEventListener(ON_AFTER_CLONE, this);
		}
	}
	
}
